package com.ums.upos.service;

import android.app.Application;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.WindowManager;
import com.nexgo.common.ByteUtils;
import com.nexgo.common.Des;
import com.nexgo.oaf.apiv3.APIProxy;
import com.nexgo.oaf.apiv3.DeviceEngine;
import com.nexgo.oaf.apiv3.OnAppOperatListener;
import com.nexgo.oaf.apiv3.SdkResult;
import com.nexgo.oaf.apiv3.device.pinpad.CalcModeEnum;
import com.nexgo.oaf.apiv3.device.pinpad.WorkKeyTypeEnum;
import com.nexgo.oaf.apiv3.device.reader.CardReader;
import com.nexgo.oaf.apiv3.device.reader.CardSlotTypeEnum;
import com.nexgo.oaf.apiv3.hsm.HSMDevice;
import com.nexgo.oaf.apiv3.hsm.TusnData;
import com.ums.upos.GlobalDataHolder;
import com.ums.upos.service.ui.InstallDialog;
import com.ums.upos.uapi.R;
import com.ums.upos.uapi.ServiceResult;
import com.ums.upos.uapi.card.cpu.CPUCardHandler;
import com.ums.upos.uapi.card.industry.IndustryCardHandler;
import com.ums.upos.uapi.card.mifare.M1CardHandler;
import com.ums.upos.uapi.device.beeper.Beeper;
import com.ums.upos.uapi.device.cashbox.CashBoxDriver;
import com.ums.upos.uapi.device.detail.DevDetail;
import com.ums.upos.uapi.device.led.LEDDriver;
import com.ums.upos.uapi.device.logrecorder.LogRecorder;
import com.ums.upos.uapi.device.modem.ModemDriver;
import com.ums.upos.uapi.device.pinpad.PinPad;
import com.ums.upos.uapi.device.printer.Printer;
import com.ums.upos.uapi.device.reader.icc.IccCardReader;
import com.ums.upos.uapi.device.reader.icc.IccCardType;
import com.ums.upos.uapi.device.reader.icc.IccReaderSlot;
import com.ums.upos.uapi.device.reader.mag.MagCardReader;
import com.ums.upos.uapi.device.scanner.InnerScanner;
import com.ums.upos.uapi.device.serialport.SerialPortDriver;
import com.ums.upos.uapi.device.wifiprobe.WiFiProbeService;
import com.ums.upos.uapi.emv.EmvHandler;
import com.ums.upos.uapi.engine.DeviceAuthConstrants;
import com.ums.upos.uapi.engine.DeviceDetailConstrants;
import com.ums.upos.uapi.engine.DeviceInfoConstrants;
import com.ums.upos.uapi.engine.DeviceServiceEngine;
import com.ums.upos.uapi.engine.OnUninstallAppListener;
import com.ums.upos.uapi.network.NetWorkHandler;
import com.ums.upos.util.CardUtils;
import com.ums.upos.util.CsnUtils;
import com.ums.upos.util.DeviceUtils;
import com.ums.upos.util.EmvFileUtils;
import com.ums.upos.util.FileUtils;
import com.ums.upos.util.PinPadUtils;
import com.ums.upos.util.ReadUtil;
import com.ums.upos.util.SystemPropertyUtils;
import com.ums.upos.util.VersionUtils;
import com.xinguodu.ddiinterface.Ddi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import dalvik.system.PathClassLoader;

/**
 * Created by xiaox on 15-10-7.
 */
public class DeviceServiceEngineService extends BaseService {
    private final String TAG = "DeviceServiceEngineService";
    private Beeper mBeeper;
    private LEDDriver mLedDriver;
    private Printer mPrinter;
    private SerialPortDriver mSerialPortDriver;
    private InnerScanner mInnerScanner;
    private MagCardReader mMagCardReader;
    private CPUCardHandler mCpuCardHandler;
    private M1CardHandler mM1CardHandler;
    private PinPad mPinPad;
    private EmvHandler mEmvHandler;
    private NetWorkHandler mNetWorkHandler;
    private IccCardReader mIccCardReader;
    private List<IccReaderHolder> mIccReaderHolderList;
    private WiFiProbeService mWifiProbeService;
    private String mBussinessId;
    private DevDetail devDetail;

    private final String TSS_PACKAGE_NAME = "com.ums.tss.mastercontrol";
    private final String APPSTORE_PACKAGE_NAME = "com.ums.appstore";
    private final String TMS_PACKAGE_NAME = "com.ums.tms";
    //终端信息获取权限
    private final static String  DEVICE_DETAIL_PERMISSION = "com.ums.upos.api.permission.GET_DEVICE_DETAIL";
    //终端日志获取权限
    private final static String  LOGRECORDER_PERMISSION = "com.ums.upos.api.permission.SET_LOGRECORDER";

    private Logger log = LoggerFactory.getLogger(TAG);
    private DeviceServiceEngineBinder mDeviceServiceEngineBinder;
    private DeviceEngine mDeviceEngine;
    private LogRecorder mLogRecorder;

    @Override
    public IBinder onBind(Intent intent) {
        log.debug("call onBind");
        super.onBind(intent);
        return new DeviceServiceEngineBinder();
    }

    private static void createNewNativeDir(Context context) throws Exception {
        PathClassLoader pathClassLoader = (PathClassLoader) context.getClassLoader();
        Object pathList = getPathList(pathClassLoader);
        //获取当前类的属性
        Object nativeLibraryDirectories = pathList.getClass().getDeclaredField("nativeLibraryDirectories");
        ((Field) nativeLibraryDirectories).setAccessible(true);
        //获取 DEXPATHList中的属性值
        File[] files1 = (File[]) ((Field) nativeLibraryDirectories).get(pathList);
        Object filesss = Array.newInstance(File.class, files1.length + 1);
        //添加自定义.so路径
        Array.set(filesss, 0, context.getFilesDir());
        //将系统自己的追加上

        for (int i = 1; i < files1.length + 1; i++) {
            Array.set(filesss, i, files1[i - 1]);
        }

        ((Field) nativeLibraryDirectories).set(pathList, filesss);
    }

    private static Object getPathList(Object obj) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        return getField(obj, Class.forName("dalvik.system.BaseDexClassLoader"), "pathList");
    }

    private static Object getField(Object obj, Class cls, String str) throws NoSuchFieldException, IllegalAccessException {
        Field declaredField = cls.getDeclaredField(str);
        declaredField.setAccessible(true);
        return declaredField.get(obj);
    }


    private int copyFileAndReplace(String srcPath, String targetPath) {
        File srcFile = new File(srcPath);
        if (!srcFile.exists()) {
            log.debug("Original file not exist!");
            return -1;
        }
        File targetFile = new File(targetPath);
        if (targetFile.exists()) {
            log.debug("target file exist!");
            if (targetFile.length() == srcFile.length()) {
                log.debug("target file size equal origin file!");
                return 0;
            }
            log.debug("delete target file!");
            targetFile.delete();
        }
        try {
            InputStream inputStream = new FileInputStream(srcFile);
            FileOutputStream fs = new FileOutputStream(targetFile);
            byte[] buffer = new byte[10240];
            StringBuilder strTemp = new StringBuilder();
            int byteread = 0, bytesum = 0;
            while (true) {
                int result = byteread = inputStream.read(buffer);
                if (result == -1)
                    break;
                strTemp.append(ByteUtils.byteArray2HexString(Arrays.copyOf(buffer, byteread)));
                bytesum += byteread;
            }
            int lastindex = strTemp.lastIndexOf(ByteUtils.byteArray2HexString("k21_rebo".getBytes()));
            log.debug("lastindex:{}", lastindex);
            strTemp.replace(lastindex, lastindex + 16, ByteUtils.byteArray2HexString("k21_11bo".getBytes()));
            log.debug("copy bytesum:{}", bytesum);
            fs.write(ByteUtils.hexString2ByteArray(strTemp.toString()), 0, bytesum);
            inputStream.close();
            fs.close();
            return 0;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return -1;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //复制k21库
        String sysDdiLibPath = "/system/lib/libxgd_ddi_jni.so";
        String targetDdiLibPath = getFilesDir().getAbsolutePath() + "/libxgd_ddi_jni_fix.so";
        int rslt = copyFileAndReplace(sysDdiLibPath, targetDdiLibPath);
        log.debug("目标地址 targetDdiLibPath:", targetDdiLibPath);
        log.debug("copyFileAndReplace rslt:{}", rslt);
        if (0 == rslt) {
            //修改lib访问路径
            try {
                createNewNativeDir(getApplicationContext());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        mDeviceEngine = APIProxy.getDeviceEngine();
        log.debug("nexgosdk version {}", mDeviceEngine.getDeviceInfo().getSdkVer());
        log.debug("nexgosdk version {}", mDeviceEngine.getDeviceInfo().getFirmWareVer());
        GlobalDataHolder.getInstance().setDeviceEngine(mDeviceEngine);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        log.debug("call onUnbind");
        try {
            //mhl20171121 应用崩溃后完全关闭wifi探针
            if (mWifiProbeService != null) {
                WifiProbeBinder wifiProbeBinder = (WifiProbeBinder) mWifiProbeService.asBinder();
                wifiProbeBinder.closeWifiStaProbe(null);
            }
            //防止应用崩了后,再启动无法登录
            mDeviceServiceEngineBinder.logout();
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return super.onUnbind(intent);
    }


    public static String getProperty(String key, String defaultValue) {
        String value = defaultValue;
        try {
            Class<?> c = Class.forName("android.os.SystemProperties");
            Method get = c.getMethod("get", String.class, String.class);
            value = (String) (get.invoke(c, key, defaultValue));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            return value;
        }
    }

    public class DeviceServiceEngineBinder extends DeviceServiceEngine.Stub {

        public DeviceServiceEngineBinder() {
            log.info("call DeviceServiceEngineBinder!");
            mDeviceServiceEngineBinder = this;
            //服务层一起来就关闭下拉
            Settings.System.putInt(getContentResolver(), "status_bar_disabled", 1);
            //判断是否支持点阵字库，1.3.2版本导入点阵字库，1.3.8版本点阵字库支持生僻字
            boolean isSupportDotMartrix = VersionUtils.compareVersion(mDeviceEngine.getDeviceInfo().getFirmWareVer().substring(1), "1.3.8") < 0 ? false : true;
            GlobalDataHolder.getInstance().setSupportDotMatrix(isSupportDotMartrix);
            //判断是否支持非接获取卡片信息接口
            byte[] k21ver = new byte[17];
            Ddi.ddi_sys_get_firmwarever(k21ver, 2);
            String k21verstr = new String(k21ver);
            boolean isSupportGetRfCardInfo = VersionUtils.compareVersion(k21verstr.substring(8, k21verstr.length()), "170501000") < 0 ? false : true;
            GlobalDataHolder.getInstance().setSupportGetRfCardInfo(isSupportGetRfCardInfo);
            //判断是否支持脚本打印
            GlobalDataHolder.getInstance().setSupportScrpitPrint(true);
            //判断是否支持国密
            GlobalDataHolder.getInstance().setSupportChnCryptAlg(mDeviceEngine.getDeviceInfo().isSupportGM());
//            GlobalDataHolder.getInstance().setSupportChnCryptAlg(false);
            //判断是否支持TUSN
            HSMDevice mHSMDevice = GlobalDataHolder.getInstance().getSdkHSMDevice();
            TusnData tusnData = mHSMDevice.getTUSN(0, "123456".getBytes());
            //mhl20180117 将获取tusn和判断是否支持21号文的流程分开
            //解决极少量存量机器已贴tusn后标，但没有21号文密钥时
            //服务返传统SN给上层导致和后台录入TUSN不匹配的问题
            String tidsn = null;
            String sn = tusnData.getTusn();

            if(null == sn || sn.length() == 0)
                sn = mDeviceEngine.getDeviceInfo().getSn();
            else if(tusnData.getMac() != null){
                tidsn = sn;
            }
            GlobalDataHolder.getInstance().setSn(sn);
            GlobalDataHolder.getInstance().setTidsn(tidsn);
            //判断是否支持wifi探针
            String wifiProbeProp = getProperty("ro.xgd.wifiprobe.ver", "0");
            log.debug("wifiProbeProp:{}", wifiProbeProp);
            if (!wifiProbeProp.equals("0"))
                GlobalDataHolder.getInstance().setSupportWifiProbe(true);
//            GlobalDataHolder.getInstance().setSupportWifiProbe(true);
            log.info("脚本打印:{},国密:{},TUSN:{},wifi探针:{}",
                    GlobalDataHolder.getInstance().isSupportScrpitPrint(),
                    GlobalDataHolder.getInstance().isSupportChnCryptAlg(),
                    GlobalDataHolder.getInstance().getTidsn(),
                    GlobalDataHolder.getInstance().isSupportWifiProbe());
        }

        @Override
        public int login(Bundle bundle, String bussinessId) throws RemoteException {
            log.info("call login, bussinessId:{}", bussinessId);

            if (TextUtils.isEmpty(bussinessId)) {
                log.error("bussinessId isEmpty");
                return ServiceResult.LOGIN_FAIL;
            }
            //要求不判断
//            else if (bussinessId.length() != 8) {
//                log.error("bussinessId length {} err", bussinessId.length());
//                return ServiceResult.LOGIN_FAIL;
//            } else if (mBussinessId != null) {
//                //不同id重复登录
//                if (!mBussinessId.equalsIgnoreCase(bussinessId)) {
//                    log.error("already login");
//                    return ServiceResult.LOGIN_FAIL;
//                }
//            }
            else {
                String[] callingApp = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
                if (null != callingApp && callingApp.length > 0) {
                    boolean flag = false;
                    for (String app : callingApp) {
                        log.debug("callingApp {}", app);
                        if ("00000000".equals(bussinessId)) {
                            if (TSS_PACKAGE_NAME.equals(app)) {
                                flag = true;
                                break;
                            }
                        }
                    }
                    if ("00000000".equals(bussinessId) && !flag) {
                        return ServiceResult.Device_Not_Ready;
                    }
                }
            }
            if (!bussinessId.equals(mBussinessId)) {
                clean();
            }
            mBussinessId = bussinessId;
            GlobalDataHolder.getInstance().setBussinessId(bussinessId);
            GlobalDataHolder.getInstance().setWorkMode(0);
            if (bundle != null) {
                int workMode = bundle.getInt("WorkMode", 0);
                if (workMode == 0) {
                    workMode = bundle.getInt("workMode", 0);
                }
                log.debug("登录服务传入的workMode为：{}", workMode);
                GlobalDataHolder.getInstance().setWorkMode(workMode);
            } else {
                //案例 A0001
                log.error("bundle is null");
                return ServiceResult.LOGIN_FAIL;
            }
            if (EmvFileUtils.isEmvFileExist(bussinessId)) {
                log.debug("ServiceResult.LOGIN_SUCCESS");
                return ServiceResult.LOGIN_SUCCESS;
            }
            log.debug("ServiceResult.LOGIN_SUCCESS_NOT_EMV_FILE");
            return ServiceResult.LOGIN_SUCCESS_NOT_EMV_FILE;
        }

        private void clean() {
            mBeeper = null;
            mLedDriver = null;
            mPrinter = null;
            mInnerScanner = null;
            mMagCardReader = null;
            mIccCardReader = null;
            mCpuCardHandler = null;
            mM1CardHandler = null;
            mPinPad = null;
            mEmvHandler = null;
            mNetWorkHandler = null;
            mBussinessId = null;

            GlobalDataHolder.getInstance().setBussinessId(null);
            GlobalDataHolder.getInstance().setWorkMode(0);
            GlobalDataHolder.getInstance().getIccReaderHolderList().clear();

            mDeviceEngine.getCPUCardHandler(CardSlotTypeEnum.RF).powerOff();
            mDeviceEngine.getCPUCardHandler(CardSlotTypeEnum.ICC1).powerOff();
            mDeviceEngine.getCPUCardHandler(CardSlotTypeEnum.ICC2).powerOff();
            mDeviceEngine.getCPUCardHandler(CardSlotTypeEnum.ICC3).powerOff();
            mDeviceEngine.getCPUCardHandler(CardSlotTypeEnum.PSAM1).powerOff();
            mDeviceEngine.getCPUCardHandler(CardSlotTypeEnum.PSAM2).powerOff();
            mDeviceEngine.getCPUCardHandler(CardSlotTypeEnum.PSAM3).powerOff();
            mDeviceEngine.getCardReader().stopSearch();
        }

        @Override
        public void logout() throws RemoteException {
            log.info("call logout");
            clean();
        }

        @Override
        public Bundle getDevInfo() throws RemoteException {
            log.info("call getDevInfo");
            String ver = "";
            try {
                PackageInfo pi = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
                ver = String.valueOf(pi.versionName);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }

            String csn = "";
            String model = Build.MODEL;
//            String model = "N3";
//            String model = "N5";
            String vendor = "XGD";
            String osVer = Build.VERSION.RELEASE;
            String commSign = "0";
            String property = SystemPropertyUtils.getProperty("ro.ums.manufacturer.info");
            log.trace("ro.ums.manufacturer.info {}", property);
            if (!TextUtils.isEmpty(property)) {
                String[] pro = property.split("\\|");
                if (pro.length == 4) {
                    if (!TextUtils.isEmpty(pro[0])) {
                        vendor = pro[0];
                    }
                    if (!TextUtils.isEmpty(pro[3])) {
                        commSign = pro[3];
                    }
                }
            }
            csn = CsnUtils.getCsn();
            log.trace("获取的csn为：{}", csn);
            Bundle bundle = new Bundle();
            bundle.putString(DeviceInfoConstrants.COMMOM_VENDOR, vendor);
            bundle.putString(DeviceInfoConstrants.COMMOM_MODEL, model);
//            bundle.putString(DeviceInfoConstrants.COMMOM_SN, GlobalDataHolder.getInstance().getSn());
            bundle.putString(DeviceInfoConstrants.COMMOM_SN, "00000404N5000237147");
            bundle.putString(DeviceInfoConstrants.COMMOM_OS_VER, osVer);
            bundle.putString(DeviceInfoConstrants.COMMON_SERVICE_VER, ver);
//            bundle.putString(DeviceInfoConstrants.DEVICE_ID, csn);
            bundle.putString(DeviceInfoConstrants.DEVICE_ID, "00000404N5000237147");
            bundle.putString(DeviceInfoConstrants.IS_COMM_SIG, commSign);
            //唯一终端序列号
//            bundle.putString(DeviceInfoConstrants.TID_SN, GlobalDataHolder.getInstance().getTidsn());
            bundle.putString(DeviceInfoConstrants.TID_SN, "00000404N5000237147");
            log.trace("获取的tsn为：{}", GlobalDataHolder.getInstance().getSn());

            //是否支持国密
            bundle.putString(DeviceInfoConstrants.IS_SUPPORT_CHN_CRYPT_ALG,
                    GlobalDataHolder.getInstance().isSupportChnCryptAlg() ? "1" : "0");
            //是否支持脚本打印
            bundle.putString(DeviceInfoConstrants.IS_SUPPORT_SCRIPT_PRINT,
                    GlobalDataHolder.getInstance().isSupportScrpitPrint() ? "1" : "0");
            //是否支持扫码优化
            boolean isSupportScanOptimize = true;
            bundle.putString(DeviceInfoConstrants.IS_SUPPORT_SCAN_OPTIMIZE, isSupportScanOptimize ? "1" : "0");

            //是否支持wifi探针
            bundle.putString(DeviceInfoConstrants.IS_SUPPORT_WIFIPROBE, GlobalDataHolder.getInstance().isSupportWifiProbe() ? "1" : "0");

            log.debug("\nCOMMOM_VENDOR:{},COMMOM_MODEL:{},SN:{}\nCOMMOM_OS_VER:{},COMMON_SERVICE_VER:{}\n" +
                            "DEVICE_ID:{},IS_COMM_SIG:{},TID_SN:{}\nIS_SUPPORT_CHN_CRYPT_ALG:{}," +
                            "IS_SUPPORT_SCRIPT_PRINT:{},IS_SUPPORT_WIFIPROBE:{}",
                    vendor, model, GlobalDataHolder.getInstance().getSn(),
                    osVer, ver, csn, commSign,
                    GlobalDataHolder.getInstance().getTidsn(),
                    GlobalDataHolder.getInstance().isSupportChnCryptAlg(),
                    GlobalDataHolder.getInstance().isSupportScrpitPrint(),
                    GlobalDataHolder.getInstance().isSupportWifiProbe());
            return bundle;
        }

        @Override
        public Bundle getDevDetail() throws RemoteException {
            log.info("call getDevDetail");

            int check = checkCallingPermission(DEVICE_DETAIL_PERMISSION);
            log.info("getDevDetail check:"+check);
            if(check==PackageManager.PERMISSION_DENIED){

                if(DeviceUtils.isRightfulCalling(mContext,DEVICE_DETAIL_PERMISSION)){
                    log.info("call getDevDetail PERMISSION_DENIED");
                    throw new SecurityException("Permission denial: com.ums.upos.api.permission.GET_DEVICE_DETAIL");
                }
            }
            if(devDetail==null){
                devDetail = new DevDetail(getApplicationContext());
            }
            Bundle bundle =  devDetail.getDevDetails();

            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
            log.info("当前时间："+df.format(new Date())+" 终端信息："+bundle.toString());

            return bundle;

        }

        @Override
        public LogRecorder getLogRecorder() throws RemoteException {
            log.info("call getLogRecorder");

            int check = checkCallingPermission(LOGRECORDER_PERMISSION);
            log.info("getLogRecorder check:"+check);
            if(check==PackageManager.PERMISSION_DENIED){

                if(DeviceUtils.isRightfulCalling(mContext,LOGRECORDER_PERMISSION)){
                    log.info("call getLogRecorder PERMISSION_DENIED");
                    throw new SecurityException("Permission denial: com.ums.upos.api.permission.SET_LOGRECORDER");
                }
            }
            if (mLogRecorder != null) return mLogRecorder;
            LogRecorderBinder binder = new LogRecorderBinder(mContext);
            mLogRecorder = LogRecorder.Stub.asInterface(binder);
            return mLogRecorder;
        }

        @Override
        public Beeper getBeeper() throws RemoteException {
            log.info("call getBeeper");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mBeeper != null) return mBeeper;
            mBeeper = GlobalDataHolder.getInstance().getBeeper();
            if (mBeeper != null) return mBeeper;
            log.info("getBeeper new BeeperBinder!");
            BeeperBinder binder = new BeeperBinder(mContext);
            mBeeper = Beeper.Stub.asInterface(binder);
            GlobalDataHolder.getInstance().setBeeper(mBeeper);
            return mBeeper;
        }

        @Override
        public LEDDriver getLEDDriver() throws RemoteException {
            log.info("call getLEDDriver");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mLedDriver != null) return mLedDriver;
            LEDBinder binder = new LEDBinder();
            mLedDriver = LEDDriver.Stub.asInterface(binder);
            return mLedDriver;
        }

        @Override
        public Printer getPrinter() throws RemoteException {
            log.info("call getPrinter");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mPrinter != null) return mPrinter;
            PrinterBinder binder = new PrinterBinder(mContext);
            mPrinter = Printer.Stub.asInterface(binder);
            return mPrinter;
        }

        @Override
        public InnerScanner getInnerScanner() throws RemoteException {
            log.info("call getInnerScanner");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mInnerScanner != null) return mInnerScanner;
            ScannerBinder binder = new ScannerBinder(mContext);
            mInnerScanner = InnerScanner.Stub.asInterface(binder);
            return mInnerScanner;
        }

        @Override
        public ModemDriver getModemDriver() throws RemoteException {
            log.info("call getModemDriver");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            return null;
        }

        @Override
        public SerialPortDriver getSerialPortDriver(int portNo) throws RemoteException {
            log.info("call getSerialPortDriver");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }

            if (portNo >= 5) return null;
            if (mSerialPortDriver != null) return mSerialPortDriver;
            SerialPortBinder binder = new SerialPortBinder(portNo);
            mSerialPortDriver = SerialPortDriver.Stub.asInterface(binder);
            return mSerialPortDriver;

        }

        @Override
        public MagCardReader getMagCardReader() throws RemoteException {
            log.info("call getMagCardReader");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mMagCardReader != null) return mMagCardReader;
            MagCardReaderBinder binder = new MagCardReaderBinder();
            mMagCardReader = MagCardReader.Stub.asInterface(binder);
            return mMagCardReader;
        }

        @Override
        public IccCardReader getIccCardReader(int slotNo) throws RemoteException {
            log.info("call getIccCardReader slotNo {}", slotNo);
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (slotNo != IccReaderSlot.ICSlOT1
                    && slotNo != IccReaderSlot.ICSlOT2
                    && slotNo != IccReaderSlot.ICSlOT3
                    && slotNo != IccReaderSlot.PSAMSlOT1
                    && slotNo != IccReaderSlot.PSAMSlOT2
                    && slotNo != IccReaderSlot.PSAMSlOT3
                    && slotNo != IccReaderSlot.RFSlOT) {
                return null;
            }

            if (slotNo != IccReaderSlot.ICSlOT1 && slotNo != IccReaderSlot.PSAMSlOT1
                    && slotNo != IccReaderSlot.PSAMSlOT2 && slotNo != IccReaderSlot.RFSlOT) {
                return null;
            }

            mIccReaderHolderList = GlobalDataHolder.getInstance().getIccReaderHolderList();
            for (IccReaderHolder holder : mIccReaderHolderList) {
                if (holder.getSlotNo() == slotNo) {
                    log.debug("reader is exist slotNo {},CardType {}", slotNo, holder.getCardType());
                    return holder.getReader();
                }
            }
            IccReaderBinder binder = new IccReaderBinder(slotNo);
            mIccCardReader = IccCardReader.Stub.asInterface(binder);
            /*IccReaderHolder iccReaderHolder = new IccReaderHolder(slotNo, mIccCardReader);
            //如果之前没有寻卡，IccReaderHolderList里没有该卡槽的readerHolder
            //为了兼容不寻卡直接操作CPU卡的操作，这里根据卡槽号设置默认卡类型
            if(IccReaderSlot.PSAMSlOT1 == slotNo || IccReaderSlot.PSAMSlOT2 == slotNo || IccReaderSlot.PSAMSlOT3 == slotNo)
                iccReaderHolder.setCardType(IccCardType.PSAM);
            else
                iccReaderHolder.setCardType(IccCardType.CPUCARD);
            CardReader sdkCardReader = GlobalDataHolder.getInstance().getDeviceEngine().getCardReader();
            CardSlotTypeEnum sdkSlotNo = CardUtils.slotConvert(slotNo);
            if(sdkCardReader.isCardExist(sdkSlotNo)){
                sdkCardReader.open(sdkSlotNo);
                sdkCardReader.setETU(sdkSlotNo, 0);
            }
            else
                return null;
            mIccReaderHolderList.add(iccReaderHolder);*/
            mIccReaderHolderList.add(new IccReaderHolder(slotNo, mIccCardReader));
            return mIccCardReader;
        }


        @Override
        public CPUCardHandler getCPUCardHandler(IccCardReader reader) throws RemoteException {
            log.info("call getCPUCardHandler");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (reader == null) return null;

            IccReaderHolder iccReaderHolder = null;
            for (IccReaderHolder holder : GlobalDataHolder.getInstance().getIccReaderHolderList()) {
                if (holder.getReader() == reader) {
                    iccReaderHolder = holder;
                    break;
                }
            }
//            if (iccReaderHolder == null || iccReaderHolder.getCardType() == null) return null;

            if (iccReaderHolder == null)
                return null;
            if (iccReaderHolder.getCardType() == null) {
                //如果之前没有寻卡，IccReaderHolderList里该卡槽的readerHolder没有卡类型
                //为了兼容不寻卡直接操作CPU卡的操作，这里根据卡槽号设置默认卡类型并重新打开卡槽
                if (IccReaderSlot.PSAMSlOT1 == iccReaderHolder.getSlotNo() ||
                        IccReaderSlot.PSAMSlOT2 == iccReaderHolder.getSlotNo() ||
                        IccReaderSlot.PSAMSlOT3 == iccReaderHolder.getSlotNo())
                    iccReaderHolder.setCardType(IccCardType.PSAM);
                else
                    iccReaderHolder.setCardType(IccCardType.CPUCARD);
                CardReader sdkCardReader = GlobalDataHolder.getInstance().getDeviceEngine().getCardReader();
                CardSlotTypeEnum sdkSlotNo = CardUtils.slotConvert(iccReaderHolder.getSlotNo());
                if (!sdkCardReader.isCardExist(sdkSlotNo))
                    return null;
//                if(sdkCardReader.isCardExist(sdkSlotNo)){
//                    sdkCardReader.open(sdkSlotNo);
//                    sdkCardReader.setETU(sdkSlotNo, 0);
//                }
//                else
//                    return null;
            }

            log.debug("reader getCardTypeResult {}", iccReaderHolder.getCardType());
            if (!iccReaderHolder.getCardType().equals(IccCardType.CPUCARD)
                    && !iccReaderHolder.getCardType().equals(IccCardType.PSAM)) {
                return null;
            }
            CPUCardHandlerBinder binder = new CPUCardHandlerBinder(reader);
            mCpuCardHandler = CPUCardHandler.Stub.asInterface(binder);
            return mCpuCardHandler;
        }

        @Override
        public M1CardHandler getM1CardHandler(IccCardReader reader) throws RemoteException {
            log.info("call getM1CardHandler");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (reader == null) return null;
            IccReaderHolder iccReaderHolder = null;
            for (IccReaderHolder holder : GlobalDataHolder.getInstance().getIccReaderHolderList()) {
                if (holder.getReader() == reader) {
                    iccReaderHolder = holder;
                    break;
                }
            }
            if (iccReaderHolder == null || iccReaderHolder.getCardType() == null) return null;
            log.debug("reader getCardTypeResult {}", iccReaderHolder.getCardType());
            if (iccReaderHolder.getCardType().equals(IccCardType.CPUCARD)
                    || iccReaderHolder.getCardType().equals(IccCardType.PSAM)) {
                return null;
            }
            M1CardHandlerBinder binder = new M1CardHandlerBinder(reader);
            mM1CardHandler = M1CardHandler.Stub.asInterface(binder);
            return mM1CardHandler;
        }

        @Override
        public PinPad getPinPad() throws RemoteException {
            log.info("call getPinPad");
            log.info("bussinessId："+mBussinessId);
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mPinPad != null) return mPinPad;
            PinPadBinder binder = new PinPadBinder(mContext);
            mPinPad = PinPad.Stub.asInterface(binder);
            return mPinPad;
        }

        @Override
        public EmvHandler getEmvHandler() throws RemoteException {
            log.info("call getEmvHandler");
            log.info("bussinessId："+mBussinessId);
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mEmvHandler != null) return mEmvHandler;
            EmvBinder binder = new EmvBinder(mContext);
            mEmvHandler = EmvHandler.Stub.asInterface(binder);
            return mEmvHandler;
        }

        @Override
        public NetWorkHandler getNetWorkHandler() throws RemoteException {
            log.info("call getNetWorkHandler");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (mNetWorkHandler != null) return mNetWorkHandler;
            NetWorkBinder binder = new NetWorkBinder(mContext);
            mNetWorkHandler = NetWorkHandler.Stub.asInterface(binder);
            return mNetWorkHandler;
        }

        @Override
        public WiFiProbeService getWiFiProbe() throws RemoteException {
            log.info("call getWiFiProbe");
//            if (mBussinessId == null) {
//                log.error("bussinessId为空");
//                return null;
//            }
            if (!GlobalDataHolder.getInstance().isSupportWifiProbe())
                return null;
            if (mWifiProbeService != null)
                return mWifiProbeService;
            WifiProbeBinder wifiProbeBinder = new WifiProbeBinder(mContext);
            mWifiProbeService = WifiProbeBinder.Stub.asInterface(wifiProbeBinder);
            return mWifiProbeService;
        }

        @Override
        public void setSystemClock(String datetime) throws RemoteException {
            log.info("call setSystemClock");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return;
            }
            log.debug("setSystemClock datetime {}", datetime);
            if (datetime == null || datetime.length() < 14) return;
            try {
                try {
                    SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault());
                    format.setLenient(false);
                    format.parse(datetime);
                } catch (ParseException e) {
                    log.error("setSystemClock datetime format err");
                    return;
                }
                //要用到系统签名的
//                Calendar c = Calendar.getInstance();
//                c.set(Calendar.YEAR, Integer.valueOf(datetime.substring(0, 4)));
//                c.set(Calendar.MONTH, Integer.valueOf(datetime.substring(4, 6)) - 1);
//                c.set(Calendar.DAY_OF_MONTH, Integer.valueOf(datetime.substring(6, 8)));
//                c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(datetime.substring(8, 10)));
//                c.set(Calendar.MINUTE, Integer.valueOf(datetime.substring(10, 12)));
//                c.set(Calendar.SECOND, Integer.valueOf(datetime.substring(12, 14)));
//
//                long when = c.getTimeInMillis();
//
//                if (when / 1000 < Integer.MAX_VALUE) {
//                    SystemClock.setCurrentTimeMillis(when);
//                }
                //与底层配合用广播的
                //修改底层月份多1个月的 bug
                StringBuilder newDataTime = new StringBuilder(datetime);
                newDataTime.replace(4, 6, String.format(Locale.getDefault(), "%02d", Integer.valueOf(datetime.substring(4, 6)) - 1));
                Intent intent = new Intent();
                intent.setAction("com.android.action.SYSTEMTIME");
                intent.putExtra("systemtime", newDataTime.toString());
                sendBroadcast(intent);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void setIMEStatus(int status) throws RemoteException {
            log.info("call setIMEStatus");
            log.error("setIMEStatus:" + status);
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return;
            }
            Intent intent = new Intent();
            intent.setAction("com.xgd.InputMethodManager");
            intent.putExtra("input", status == 0 ? "ENABLE" : "DISABLE");
            sendBroadcast(intent);
        }

        @Override
        public void installApp(final String appFilePath, final String runActivityName, final String appName) throws RemoteException {
            log.info("call installApp");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return;
            }
            log.debug("installApp appFilePath {},runActivityName {},appName {}", appFilePath, runActivityName, appName);

            if (TextUtils.isEmpty(appFilePath)) return;
            if (!FileUtils.isFileExist(appFilePath)) return;
            final Handler handler = new Handler(getMainLooper()) {
                InstallDialog installDialog;

                @Override
                public void handleMessage(Message msg) {
                    switch (msg.what) {
                        case 0:
                            installDialog = new InstallDialog(mContext, R.style.CustomDialog);
                            installDialog.getWindow().setType((WindowManager.LayoutParams.TYPE_SYSTEM_ALERT));
                            installDialog.setCanceledOnTouchOutside(false);
                            installDialog.setAppName(appName == null ? "" : appName);
                            installDialog.show();
                            break;
                        case 1:
                            installDialog.dismiss();
                            Map<String, Object> pkgInfo = ReadUtil.readAPK(appFilePath);
                            String pkgName = (String) pkgInfo.get("package");
                            log.debug("pkgName:" + pkgName);
                            log.debug("runActivityName:" + runActivityName);
                            //tss自动调起
                            if (pkgName.equals(TSS_PACKAGE_NAME)) {
                                doStartApplicationWithPackageName(pkgName);
                            }
                            break;
                        case -1:
                        default:
                            installDialog.dismiss();
                            break;
                    }
                }
            };
            handler.sendEmptyMessage(0);
            mDeviceEngine.installApp(mContext, appFilePath, new OnAppOperatListener() {
                @Override
                public void onOperatResult(int i) {
                    log.debug("onOpeartResult {}", i);
                    handler.sendEmptyMessage(i == SdkResult.Success ? 1 : -1);
                }
            });
        }

        private boolean checkPackage(String packageName) {
            try {
                if (TextUtils.isEmpty(packageName)) return false;
                getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES);
                return true;
            } catch (PackageManager.NameNotFoundException e) {
                return false;
            }
        }

        private void doStartApplicationWithPackageName(String packagename) {

            // 通过包名获取此APP详细信息，包括Activities、services、versioncode、name等等
            PackageInfo packageinfo = null;
            try {
                packageinfo = getPackageManager().getPackageInfo(packagename, 0);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            if (packageinfo == null) {
                return;
            }

            // 创建一个类别为CATEGORY_LAUNCHER的该包名的Intent
            Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
            resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
            resolveIntent.setPackage(packageinfo.packageName);

            // 通过getPackageManager()的queryIntentActivities方法遍历
            List<ResolveInfo> resolveinfoList = getPackageManager()
                    .queryIntentActivities(resolveIntent, 0);

            ResolveInfo resolveinfo = resolveinfoList.iterator().next();
            if (resolveinfo != null) {
                // packagename = 参数packname
                String packageName = resolveinfo.activityInfo.packageName;
                // 这个就是我们要找的该APP的LAUNCHER的Activity[组织形式：packagename.mainActivityname]
                String className = resolveinfo.activityInfo.name;
                // LAUNCHER Intent
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.addCategory(Intent.CATEGORY_LAUNCHER);

                // 设置ComponentName参数1:packagename参数2:MainActivity路径
                ComponentName cn = new ComponentName(packageName, className);
                intent.setComponent(cn);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                startActivity(intent);
            }
        }

        @Override
        public Bundle authDevice(String authRandom) throws RemoteException {
            log.info("call authDevice");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return null;
            }
            if (authRandom == null || authRandom.length() != 16) {
                log.error("authRandom数据错误");
                return null;
            }
            ByteBuffer data = ByteBuffer.allocate(128);
            String deviceId = CsnUtils.getCsn();
            if (TextUtils.isEmpty(deviceId)) {
                log.error("deviceId为空");
                return null;
            }
            byte[] deviceIdByte = ByteUtils.hexString2ByteArray(deviceId);
            byte[] authRandomByte = ByteUtils.hexString2ByteArray(authRandom);
            byte[] factor = new byte[16];
            System.arraycopy(authRandomByte, 0, factor, 0, authRandomByte.length);
            data.put(deviceIdByte, 4, 6);
            data.put(authRandomByte);
            data.put(new byte[]{(byte) 0x80, (byte) 0x00});
            for (int i = 8; i < 16; i++) {
                factor[i] = (byte) (~factor[i - 8]);
            }
            byte[] authData = new byte[data.position()];

            com.nexgo.oaf.apiv3.device.pinpad.PinPad sdkPinPad = mDeviceEngine.getPinPad();
            boolean isOldSolution = false;//原方案为出厂灌入三个“主”密钥,现方案为灌入三个“工作”密钥,为了兼容以前的方案，这里要判断一下机器里面有没有旧方案的三个密钥,做兼容处理
            if (sdkPinPad.isKeyExist(PinPadUtils.MAINKEY_IDX)
                    && sdkPinPad.isKeyExist(PinPadUtils.AUTHKEY_IDX)
                    && sdkPinPad.isKeyExist(PinPadUtils.APPKEY_IDX)) {
                log.debug("存在旧方案的密钥");
                isOldSolution = true;
            }
            if (isOldSolution) {
                factor = sdkPinPad.encryptByMKey(PinPadUtils.AUTHKEY_IDX, factor, factor.length);
            } else {
                factor = sdkPinPad.calcByWKey(PinPadUtils.MOBLILE_MODE_FIXED_MKEYIDX, WorkKeyTypeEnum.MACKEY, factor, factor.length, CalcModeEnum.ENCRYPT);
            }
            if (factor != null) {
                authData = Des.trides_crypt(factor, Arrays.copyOfRange(data.array(), 0, data.position()));
            }
            data.clear();
            if (authData != null) {
                Bundle bundle = new Bundle();
                log.debug("返回的认证数据：{}", ByteUtils.byteArray2HexString(authData));
                bundle.putString(DeviceAuthConstrants.AUTHDATA, ByteUtils.byteArray2HexString(authData));
                return bundle;
            }
            return null;
        }

        @Override
        public CashBoxDriver getCashBoxDriver() throws RemoteException {
            return null;
        }

        @Override
        public IndustryCardHandler getIndustryCardHandler(IccCardReader reader) throws RemoteException {
            return null;
        }

        @Override
        public void uninstallApp(String packageName, final OnUninstallAppListener listener) throws RemoteException {
            log.info("call uninstallApp");
            if (mBussinessId == null) {
                log.error("bussinessId为空");
                return;
            }
            if (listener == null) return;
            log.debug("uninstallApp packageName {}", packageName);
            if (TextUtils.isEmpty(packageName) || !checkPackage(packageName)) {
                listener.onUninstallAppResult(ServiceResult.Uninstall_App_Not_Found);
                return;
            }
            boolean flag = false;
            String[] callingApp = mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
            if (null != callingApp && callingApp.length > 0) {
                for (String app : callingApp) {
                    log.debug("callingApp {}", app);
                    if (TSS_PACKAGE_NAME.equalsIgnoreCase(app)
                            || APPSTORE_PACKAGE_NAME.equalsIgnoreCase(app)
                            || TMS_PACKAGE_NAME.equalsIgnoreCase(app)) {
                        flag = true;
                        break;
                    }
                }
            }
            if (!flag) {
                listener.onUninstallAppResult(ServiceResult.Uninstall_Wrong_Caller);
                return;
            }
            mDeviceEngine.uninstallApp(mContext, packageName, new OnAppOperatListener() {
                @Override
                public void onOperatResult(int i) {
                    log.debug("onOpeartResult {}", i);
                    try {
                        listener.onUninstallAppResult(i == SdkResult.Success ? ServiceResult.Uninstall_Success : ServiceResult.Uninstall_Other_Error);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        @Override
        public int setLanguageType(int languageType, int scope) throws RemoteException {
            log.info("call setLanguageType,languageType:{}, scope:{}", languageType, scope);
            GlobalDataHolder.getInstance().setLanguageType(languageType);
            return ServiceResult.Success;
        }
    }
}
